#pragma once

#include "ReactorThreadPool.hpp"
#include "Acceptor.hpp"
#include "Connection.hpp"
#include "IdManage.hpp"


#include <signal.h>

// 对所有模块的整合，是直接提供给组件使用者搭建高性能服务器的模块
class TcpServer
{
    // 默认超时销毁时间（以秒为单位）
    static const uint32_t DefaultTimerout = 30;

    // 连接建立完成时调用的回调
    typedef function<void(shared_ptr<Connection>)> ConnectionCallback;

    // 业务处理回调--请尽可能在一次业务处理函数中，把Buffer接收缓冲区中的数据全部处理完
    typedef function<void(shared_ptr<Connection>, Buffer *)> OperationsCallback;
    // 连接关闭时调用的回调
    typedef function<void(shared_ptr<Connection>)> CloseCallback;
    // 连接有任意事件发生时，都会调用的回调
    typedef function<void(shared_ptr<Connection>)> AnyEventCallback;
    // 用户接收缓冲区容量超限时，需要调用的回调，bool*类型的参数表示是否关闭该连接, 如果关闭请设置为true
    typedef function<void(shared_ptr<Connection>, Buffer *, bool *)> BufferCapacityExceededLimitCallback;

private:
    // 端口号
    uint16_t _port;
    // 和主线程绑定的主reactor
    Reactor _base_reactor;
    // 管理所有从属reactor线程的线程池
    ReactorThreadPool _reactor_thread_pool;

    // 管理监听套接字和主reactor绑定
    Acceptor _listen;
    // 管理所有IO连接
    unordered_map<uint64_t, shared_ptr<Connection>> _connections;

    // 超时销毁时间，即连接多长时间没通信，就释放该连接
    uint32_t _timerout;
    // 是否开启非活跃连接超时释放（默认false）
    bool _enable_inactive_release;

    // 请求协议类的上下文（对象）
    Any _context;

    // 组件使用者设置的回调//
    //  连接建立完成时调用的回调
    ConnectionCallback _connection_callback;
    // 对Buffer接收缓冲区中的数据处理时，调用的业务处理回调
    OperationsCallback _operations_callback;
    // 连接关闭时调用的回调
    CloseCallback _close_callback;
    // 连接有任意事件发生时，都会调用的回调
    AnyEventCallback _any_event_callback;
    // 用户接收缓冲区容量超限时，需要调用的回调
    BufferCapacityExceededLimitCallback _buffer_capacity_exceeded_limit_callback;
private:
    // 从管理所有Connection的_connections中删除某个Connection的智能指针对象
    void RemoveConnectionInLoop(shared_ptr<Connection> connection)
    {
        // 连接存在才能删除
        if (_connections.find(connection->ConnectionID()) != _connections.end())
        {
            // 删除连接
            _connections.erase(connection->ConnectionID());
        }
        else
        {
            LOG(LogLevel::WARNING) << "试图删除不存在的连接,代码逻辑出现问题";
        }
    }
    // 使用主Reactor的RunInLoop封装RemoveConnectionInLoop
    void RemoveConnection(shared_ptr<Connection> connection)
    {
        _base_reactor.RunInLoop(std::bind(&TcpServer::RemoveConnectionInLoop, this, connection));
    }

    // 添加定时任务,返回值为定时任务ID
    void AddTimerTaskInLoop(uint64_t timerid, const timer_task_t &task, uint32_t timeout)
    {
        // 用户设置的定时任务交给主Reactor
        _base_reactor.AddTimerTask(timerid, timeout, task);
    }
    // 刷新定时任务，延迟超时时间
    void RefreshTimerTaskInLoop(uint64_t id, uint32_t time)
    {
        _base_reactor.RefreshTimerTask(id, time);
    }
    // 取消指定定时任务
    void CanceledTimerTaskInLoop(uint64_t id)
    {
        _base_reactor.CanceledTimerTask(id);
    }
    // 为获取到的新连接创建Connection对象，对其进行管理（是设置给_listen的）
    void HandleNewConnection(int fd)
    {
        // 连接对应的定时销毁任务的ID
        uint64_t timer_id = 0;
        if (_enable_inactive_release == true)
        {
            // 申请定时任务id
            timer_id = IdManager::GetId();
        }
        // 申请连接ID
        uint64_t new_connection_id = IdManager::GetId();

        // 创建Connection对象
        shared_ptr<Connection> newconnection = make_shared<Connection>(
            _reactor_thread_pool.NeaxReactor(),
            fd,
            new_connection_id,
            timer_id,
            _timerout);

        // 给连接设置上下文空对象,连接自己接收到请求报文时填充
        newconnection->SetContext(_context);

        // 把组件使用者注册的回调设置给它
        newconnection->SetConnectionCallback(_connection_callback);
        newconnection->SetOperationsCallback(_operations_callback);
        newconnection->SetCloseCallback(_close_callback);
        newconnection->SetAnyEventCallback(_any_event_callback);
        newconnection->SetBufferCapacityExceededLimitCallback(_buffer_capacity_exceeded_limit_callback);

        // 把TcpServer的连接关闭时要调用的回调注册给它
        newconnection->SetServerCloseCallback(
            std::bind(&TcpServer::RemoveConnection,
                      this,
                      std::placeholders::_1));

        // 根据是否进行超时销毁销毁，决定是否添加定时任务
        if (_enable_inactive_release == true)
        {
            // 启动连接的超时销毁
            newconnection->EnableInactiveRelease(_timerout);
        }
        // 连接建立完成之后，需要做的各种设置和初始化
        newconnection->Establelished();
        // 添加到哈希表_connections中进行管理
        _connections.insert({new_connection_id, newconnection});
    }

public:
    TcpServer(uint16_t port)
        : _port(port),
          _reactor_thread_pool(&_base_reactor),
          _listen(&_base_reactor, port),
          _timerout(DefaultTimerout),
          _enable_inactive_release(false),
          _connection_callback(nullptr),
          _operations_callback(nullptr),
          _close_callback(nullptr),
          _any_event_callback(nullptr),
          _buffer_capacity_exceeded_limit_callback(nullptr)
    {
        // 给监听套接字设置回调
        _listen.SetAcceptCallback(std::bind(
            &TcpServer::HandleNewConnection,
            this,
            std::placeholders::_1));
    }
    // 设置从属Reactor线程个数
    void SetThreadConnection(uint32_t count)
    {
        _reactor_thread_pool.SetSubordReactorThreadCount(count);
    }
    // 根据组件使用者指定的秒（参数sec）启动非活跃连接超时销毁
    void EnableInactiveRelease(int sec)
    {
        // 设置超时时间
        _timerout = sec;
        _enable_inactive_release = true;
    }
    // 关闭非活跃连接超时销毁
    void CancelInactiveRelease()
    {
        // 设置超时时间
        _timerout = 0;
        _enable_inactive_release = false;
    }
    // 添加定时任务(给组件使用者提供的),返回值为定时任务ID
    uint64_t AddTimerTask(const timer_task_t &task, uint32_t time)
    {
        uint64_t timerid = IdManager::GetId();
        _base_reactor.RunInLoop(std::bind(&TcpServer::AddTimerTaskInLoop, this, timerid, std::ref(task), time));
        return timerid;
    }
    // 刷新定时任务，更新超时时间
    void RefreshTimerTask(uint64_t id, uint32_t time)
    {
        _base_reactor.RunInLoop(std::bind(&TcpServer::RefreshTimerTaskInLoop, this, id, time));
    }
    // 取消指定定时任务
    void CanceledTimerTask(uint64_t id)
    {
        _base_reactor.RunInLoop(std::bind(&TcpServer::CanceledTimerTaskInLoop, this, id));
    }
    // 设置（切换）协议
    // 请最好在Start之前进行设置（切换）
    // 如果在服务器运行过程中切换的话，就只对新连接奏效
    // 上下文对象只需要类型正确即可，内容由连接自己工作时填充
    void HandoffAgreement(const Any &context,
                          const OperationsCallback &oper_callback,
                          const BufferCapacityExceededLimitCallback &exceeded_limit_callback,
                          const ConnectionCallback &conn_callback = nullptr,
                          const CloseCallback &close_callback = nullptr,
                          const AnyEventCallback &any_callback = nullptr)
    {
        // 设置上下文空对象
        _context = context;
        // 设置对应回调
        _connection_callback = conn_callback;
        _operations_callback = oper_callback;
        _close_callback = close_callback;
        _any_event_callback = any_callback;
        _buffer_capacity_exceeded_limit_callback=exceeded_limit_callback;
    }

    // 设置上下文类型，设置的对象为协议上下文类的初始化好的对象即可，连接自己会填充具体的上下文
    void SetContext(const Any &context)
    {
        _context = context;
    }

    // 设置业务处理回调
    void SetOperationsCallback(const OperationsCallback &oper_callback)
    {
        _operations_callback = oper_callback;
    }
    // 设置业务连接建立完成后的回调
    void SetConnectionCallback(const ConnectionCallback &conn_callback)
    {
        _connection_callback = conn_callback;
    }
    // 设置业务连接关闭回调
    void SetCloseCallback(const CloseCallback &close_callback)
    {
        _close_callback = close_callback;
    }
    // 设置连接任意事件触发都会调用的回调
    void SetAnyEventCallback(const AnyEventCallback &any_callback)
    {
        _any_event_callback = any_callback;
    }
    // 设置用户接收缓冲区容量超限时，需要调用的回调(bool*类型的参数表示是否需要继续对该连接进行读取)
    void SetBufferCapacityExceededLimitCallback(const BufferCapacityExceededLimitCallback &exceeded_limit_callback)
    {
        _buffer_capacity_exceeded_limit_callback = exceeded_limit_callback;
    }

    // 设置用户（连接）接收缓冲区最大的容量(默认64MB)
    void SetMaxReadBufferCapacity(uint64_t capacity)
    {
        Connection::SetMaxReadBufferCapacity(capacity);
    }

    void Start()
    {
        // 创建并启动所有从属Reactor线程
        _reactor_thread_pool.CreateAndStart();
        // 开始监听(即开启监听套接字读事件监控)
        _listen.Listen();
        // 启动主Reactor
        _base_reactor.Start();
    }
};

//定义其全局变量，用于忽略SIGPIPE信号
class NetWork
{
public:
    NetWork()
    {
        signal(SIGPIPE, SIG_IGN);
    }
};

// 忽略SIGPIPE信号
NetWork nw;